package com.qqt.csr.common.acl.auth;

import com.alibaba.fastjson2.JSONObject;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.collect.Maps;
import com.qqt.csr.common.acl.auth.resp.AuthInfoDTO;
import com.qqt.csr.common.exception.BaseException;
import com.qqt.csr.common.exception.BizException;
import com.qqt.csr.common.exception.StatusCode;
import com.qqt.csr.common.utils.CacheKeyUtil;
import com.qqt.csr.common.utils.HttpClientUtil;
import com.qqt.csr.common.utils.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class AuthServiceClient {
    private Cache<String, String> APP_ACCESS_TOKEN_CACHE = Caffeine.newBuilder()
            .maximumSize(1)
            .expireAfterWrite(CacheKeyUtil.EXPIRE_TIME_30S, TimeUnit.MILLISECONDS)
            .build();
    @Value("${aiCustomer.authorizationUrl}")
    private String authorizationUrl;
    @Value("${aiCustomer.tenantId}")
    private String tenantId;
    @Value("${aiCustomer.apiKey}")
    private String apiKey;
    @Value("${aiCustomer.appAccessTokenUrl}")
    private String appAccessTokenUrl;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 校验token，并返回授权信息
     *
     * @param authorizationToken
     * @return
     */
    public AuthInfoDTO getAuthInfoDto(String authorizationToken) {
        try {
            log.info("开始调用智能客服授权验证接口，authorizationToken:{}", authorizationToken);
            Map<String, String> headerMap = new HashMap<>();
            headerMap.put("Authorization", authorizationToken);
            headerMap.put("Tenant-Id", tenantId);
            headerMap.put("accessToken", getAppAccessToken());
            String respStr = HttpClientUtil.get(authorizationUrl, Maps.newHashMap(), headerMap);
            log.info("结束调用智能客服授权验证接口，resp:{}", respStr);
            JSONObject respJson = Optional.ofNullable(JsonUtil.toObject(respStr, JSONObject.class)).orElseGet(JSONObject::new);
            if (!"200".equalsIgnoreCase(respJson.getString("code"))
                    || StringUtils.isBlank(respJson.getString("data"))) {
                String errorMsg = Optional.ofNullable(respJson.getString("msg")).orElse(StatusCode.Common.NO_TOKEN.getMessage());
                throw new BizException(StatusCode.Common.NO_TOKEN.getCode(), errorMsg);
            }
            return JsonUtil.toObject(respJson.getString("data"), AuthInfoDTO.class);
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            log.error("调用智能客服授权验证接口异常", e);
            throw new BizException(StatusCode.Common.THIRD_API_ERROR);
        }
    }

    /**
     * 调用智能客服接口，需要获取应用的accessToken
     *
     * @return
     */
    public String getAppAccessToken() {
        String accessToken = Optional.ofNullable(APP_ACCESS_TOKEN_CACHE.getIfPresent(CacheKeyUtil.AiCustomer.ACCESS_TOKEN))
                .filter(StringUtils::isNotBlank)
                .orElseGet(() -> {
                    String at = (String) redissonClient.getBucket(CacheKeyUtil.AiCustomer.ACCESS_TOKEN).get();
                    if(StringUtils.isNotBlank(at)){
                        APP_ACCESS_TOKEN_CACHE.put(CacheKeyUtil.AiCustomer.ACCESS_TOKEN, at);
                        return at;
                    }
                    return StringUtils.EMPTY;
                });
        if (StringUtils.isNotBlank(accessToken)) {
            return accessToken;
        }
        try {
            log.info("开始调用智能客服appAccessToken接口");
            Map<String, String> headerMap = new HashMap<>();
            headerMap.put("apiKey", apiKey);
            String respStr = HttpClientUtil.get(appAccessTokenUrl, Maps.newHashMap(), headerMap);
            log.info("结束调用智能客服appAccessToken接口，resp:{}", respStr);
            JSONObject respJson = Optional.ofNullable(JsonUtil.toObject(respStr, JSONObject.class)).orElseGet(JSONObject::new);
            accessToken = respJson.getString("data");
            if (!"200".equalsIgnoreCase(respJson.getString("code")) || StringUtils.isBlank(accessToken)) {
                String errorMsg = Optional.ofNullable(respJson.getString("msg")).orElse(StatusCode.Common.NO_TOKEN.getMessage());
                throw new BizException(StatusCode.Common.NO_TOKEN.getCode(), errorMsg);
            }
            APP_ACCESS_TOKEN_CACHE.put(CacheKeyUtil.AiCustomer.ACCESS_TOKEN, accessToken);
            redissonClient.getBucket(CacheKeyUtil.AiCustomer.ACCESS_TOKEN).set(accessToken, Duration.of(CacheKeyUtil.EXPIRE_TIME_2H - CacheKeyUtil.EXPIRE_TIME_60S, ChronoUnit.MILLIS));
            return accessToken;
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            log.error("调用智能客服appAccessToken接口异常", e);
            throw new BizException(StatusCode.Common.THIRD_API_ERROR);
        }
    }
}
